use egui_dy::eframe::egui::{self, vec2, Align2, Color32, Id, InputState, Rect, Rounding, Sense, Stroke, Ui};

use crate::{char_utils::char_to_italic_str, math::{Equation, Monomial, PolyChild, Polynomial, PropContent, PropSys, Sign, Signed, Value}, ui_utils::{child_ui, no_select_label}};

use super::set_math_font_size;

#[derive(Debug, PartialEq, Default, Clone, Copy)]
enum Side {
    #[default]
    Left,
    Right
}

#[derive(Debug, Default)]
pub struct InferMath {
    no_new_when_nec_and_suf: bool,
    chosen: Vec<usize>,
    target_pos: Vec<usize>,
    target_side: Side,
    click_pos: Vec<usize>,
    drag_pos: Vec<usize>,
    drag_sides: Vec<Side>,
    released: bool,
    action_target: ActionTarget,
}
#[derive(Default, Debug, PartialEq, Clone, Copy)]
enum ActionTarget {
    Chosen,
    #[default]
    Equation
}
pub enum InferResult {
    Suffi(PropContent),
    NecAndSuf(PropContent),
}
fn first_diff_pos(p1: &[usize], p2: &[usize], len: usize) -> usize {
    for i in 0..len {
        if p1[i] != p2[i] {
            return i;
        }
    }
    len
}

pub fn update_infer_math(ui: &mut Ui, prop_index: usize, prop_sys: &mut PropSys, infer_math: &mut InferMath) -> Option<usize> {
    let prop = &mut prop_sys[prop_index];
    let infer_result = if let Some(infer_result) = match &prop.content {
        PropContent::Eq(equation) => update_inferring_equation(ui, equation, infer_math),
        PropContent::None => None
    } {
        infer_result
    } else {
        return None;
    };
    match infer_result {
        InferResult::NecAndSuf(prop_content) => {
            if infer_math.no_new_when_nec_and_suf {
                prop.content = prop_content;
                *infer_math = InferMath {
                    no_new_when_nec_and_suf: infer_math.no_new_when_nec_and_suf,
                    action_target: infer_math.action_target,
                    ..Default::default()
                };
                return None;
            }
            let new_pos = prop.rect.left_bottom() + vec2(0.0, 15.0);
            let new_focus = prop_sys.create_eqv(prop_content, prop_index, new_pos);
            Some(new_focus)
        },
        InferResult::Suffi(_) => {
            ui.label("Does not support yet");
            return None;
        }
    }
}

pub fn update_inferring_equation(ui: &mut Ui, equation: &Equation, infer_math: &mut InferMath) -> Option<InferResult> {
    let size = 17.0;
    let mut pos = vec![0];
    let update_eq_res = |i: &InputState, rect: Rect, infer_math: &mut InferMath| {
        if !i.pointer.is_decidedly_dragging() {
            return;
        }
        let pointer = i.pointer.interact_pos().unwrap();
        if !rect.contains(pointer) {
            return;
        }
        let middle = 0.5 * (rect.max.x + rect.min.x);
        if pointer.x < middle {
            infer_math.drag_pos.push(0);
            infer_math.drag_sides.push(Side::Right);
        } else {
            infer_math.drag_pos.push(1);
            infer_math.drag_sides.push(Side::Left);
        }
        if i.pointer.primary_released() {
            infer_math.released = true;
        } else {
            infer_math.released = false;
        }
    };
    ui.scope(|ui| {
        set_math_font_size(ui, size);
        ui.style_mut().spacing.item_spacing.x = 0.0;
        ui.horizontal(|ui| {
            update_inferring_value(ui, &equation.left, infer_math, size, &mut pos);
            let rect = child_ui(ui, |ui| {
                ui.allocate_space(vec2(size * 0.2, size));
                no_select_label(ui, "=");
                ui.allocate_space(vec2(size * 0.2, size));
            }).response.rect;
            ui.input(|i| {
                update_eq_res(i, rect, infer_math);
            });
            pos[0] = 1;
            update_inferring_value(ui, &equation.right, infer_math, size, &mut pos);
            // ui.interact(ui.min_rect(), ui.next_auto_id(), Sense::drag());
        });
    });
    if infer_math.click_pos.len() > 0 {
        let click_pos = &infer_math.click_pos;
        let chosen = &mut infer_math.chosen;
        if click_pos.len() == chosen.len() {
            let diff_pos = first_diff_pos(&click_pos, &chosen, chosen.len());
            if diff_pos == chosen.len() {
                chosen.truncate(1)
            } else {
                chosen[diff_pos] = click_pos[diff_pos];
                chosen.truncate(diff_pos + 1);
            }
        } else if click_pos.len() > chosen.len() {
            let diff_pos = first_diff_pos(&click_pos, &chosen, chosen.len());
            if diff_pos == chosen.len() {
                chosen.push(click_pos[diff_pos]);
            } else {
                chosen[diff_pos] = click_pos[diff_pos];
                chosen.truncate(diff_pos + 1);
            }
        } else if click_pos.len() < chosen.len() {
            let diff_pos = first_diff_pos(&click_pos, &chosen, click_pos.len());
            if diff_pos == click_pos.len() {
                chosen.truncate(diff_pos)
            } else {
                chosen[diff_pos] = click_pos[diff_pos];
                chosen.truncate(diff_pos + 1);
            }
        }
        infer_math.click_pos.clear();
    }
    let update_action_target = |ui: &mut Ui| {
        ui.label("Action target:");
        let res1 = ui.selectable_label(infer_math.action_target == ActionTarget::Chosen, "Chosen");
        if infer_math.chosen.is_empty() {
            res1.on_hover_text("No selections");
        } else {
            if res1.clicked() {
                infer_math.action_target = ActionTarget::Chosen
            }
        }
        if ui.selectable_label(infer_math.action_target == ActionTarget::Equation, "Equation").clicked() {
            infer_math.action_target = ActionTarget::Equation;
        };
    };
    let mut possible_result: Option<InferResult> = None;
    egui::Area::new(Id::new("infer operations"))
    .anchor(Align2::CENTER_BOTTOM, [0.0, 0.0])
    .show(ui.ctx(), |ui| {
        egui::Frame::window(ui.style()).show(ui, |ui| {
            ui.horizontal(|ui| {
                ui.vertical(update_action_target);
                ui.separator();
                ui.vertical(|ui| {
                    ui.label("Action result:").on_hover_text("What will happen when the action result in a proposition equivalent to the original one");
                    ui.selectable_value(&mut infer_math.no_new_when_nec_and_suf, false, "New")
                        .on_hover_text("Create a new proposition");
                    ui.selectable_value(&mut infer_math.no_new_when_nec_and_suf, true, "Change")
                        .on_hover_text("Modify the original proposition");
                });
                ui.separator();
                ui.vertical(|ui| {
                    ui.label("Simplify:");
                    let res1 =  ui.button("((()))").on_hover_text("simplify brackes");
                    if res1.clicked() {
                        let mut simplified = Equation::new(Value::Num(0), Value::Num(0));
                        simplified.left = equation.left.simplify_brackets();
                        simplified.right = equation.right.simplify_brackets();
                        possible_result = Some(InferResult::NecAndSuf(PropContent::Eq(simplified)));
                    }
                });
                ui.separator();
                ui.label("Second");
            });
        });
    });
    if let Some(_) = possible_result {
        return possible_result;
    }
    if infer_math.drag_pos.len() > 0 {
        if infer_math.chosen.len() == 0 {
            infer_math.drag_pos.clear();
            infer_math.drag_sides.clear();
            return None;
        }
        let chosen = &infer_math.chosen;
        let infer_result = if chosen.len() == 1 {
            drag_eq_part(ui, equation, infer_math, size)
        } else if infer_math.drag_pos.len() >= chosen.len() && infer_math.drag_pos[..chosen.len()-1] == chosen[..chosen.len()-1] {
            drag_in_parent(ui, equation, infer_math, size)
        } else if chosen.len() == 2 {
            if let Value::Poly(polynomial) = equation.child(chosen[0]).unwrap() {
                drag_from_eq_poly(ui, equation, infer_math, size, polynomial)
            } else {
                None
            }
        } else {
            None
        };
        infer_math.drag_pos.clear();
        infer_math.drag_sides.clear();
        if infer_result.is_some() {
            return infer_result;
        }
    }
    None
}
fn drag_from_eq_poly(ui: &mut Ui, equation: &Equation, infer_math: &mut InferMath, size: f32, polynomial: & Polynomial) -> Option<InferResult> {
    let chosen = &infer_math.chosen;
    let hover = &infer_math.drag_pos;
    let hover_sides = &infer_math.drag_sides;
    if hover[0] == chosen[0] {
        return None;
    }
    if infer_math.released {
        let mut chosen_poly = polynomial.clone();
        if let Value::Poly(mut other_poly) = equation.child(hover[0]).unwrap().clone() {
            let neg_child = -chosen_poly.remove(chosen[1]);
            if hover.len() == 1 {
                other_poly.insert(0, neg_child);
            } else {
                other_poly.insert(hover[1] + hover_sides[1] as usize, neg_child);
            }
            let mut new_eq = Equation::new(Value::Num(0), Value::Num(0));
            *new_eq.child_mut(chosen[0]).unwrap() = Value::Poly(chosen_poly);
            *new_eq.child_mut(hover[0]).unwrap() = Value::Poly(other_poly);
            Some(InferResult::NecAndSuf(PropContent::Eq(new_eq)))
        } else {
            let neg_child = -chosen_poly.remove(chosen[1]);
            let otherside_child = equation.child(hover[0]).unwrap().clone().into();
            let other_poly = if hover_sides[0] == Side::Left {
                Polynomial::new(vec![neg_child, otherside_child])
            } else {
                Polynomial::new(vec![otherside_child, neg_child])
            };
            let mut new_eq = Equation::new(Value::Num(0), Value::Num(0));
            *new_eq.child_mut(chosen[0]).unwrap() = Value::Poly(chosen_poly);
            *new_eq.child_mut(hover[0]).unwrap() = Value::Poly(other_poly);
            Some(InferResult::NecAndSuf(PropContent::Eq(new_eq)))
        }
    } else {
        let chosen_child = &polynomial[chosen[1]];
        let neg_chosen = -chosen_child;
        render_hover(ui, size, |ui| neg_chosen.render(ui, size));
        if let Value::Poly(_) = equation.child(hover[0]).unwrap() {
            if hover.len() == 1 {
                infer_math.target_pos.push(hover[0]);
                infer_math.target_side = hover_sides[0];
            } else {
                infer_math.target_pos.extend_from_slice(&hover[..2]);
                infer_math.target_side = hover_sides[1];
            }
        } else {
            infer_math.target_pos.push(hover[0]);
            infer_math.target_side = hover_sides[0];
        }
        None
    }
}
fn drag_in_parent(ui: &mut Ui, equation: &Equation, infer_math: &mut InferMath, size: f32) -> Option<InferResult> {
    let chosen = &infer_math.chosen;
    let len = chosen.len();
    let hover = infer_math.drag_pos[len - 1];
    let hover_side = infer_math.drag_sides[len - 1];
    if infer_math.released {
        let mut new_eq = equation.clone();
        let parent = new_eq.get_mut(&chosen[..len - 1]).unwrap();
        if let Value::Mono(monomial) = parent {
            monomial.move_within(chosen[len - 1], hover + hover_side as usize);
        } else if let Value::Poly(polynomial) = parent {
            polynomial.move_within(chosen[len - 1], hover + hover_side as usize)
        }
        Some(InferResult::NecAndSuf(PropContent::Eq(new_eq)))
    } else {
        let parent = equation.get(&chosen[..len - 1]).unwrap();
        if let Value::Mono(monomial) = parent {
            let chosen_value = &monomial[chosen[len - 1]];
            infer_math.target_pos.extend_from_slice(&infer_math.drag_pos[..len]);
            infer_math.target_side = hover_side;
            render_hover(ui, size, |ui| chosen_value.render(ui, size));
        } else if let Value::Poly(polynomial) = parent {
            let index = chosen[len - 1];
            let chosen_value = &polynomial.children[index];
            if index == 0 {
                render_hover(ui, size, |ui| chosen_value.inner.render(ui, size));
            } else {
                render_hover(ui, size, |ui| chosen_value.render(ui, size));
            }
            infer_math.target_pos.extend_from_slice(&infer_math.drag_pos[..len]);
            infer_math.target_side = hover_side;
        }
        None
    }
}
fn drag_eq_part(ui: &mut Ui, equation: &Equation, infer_math: &mut InferMath, size: f32) -> Option<InferResult> {
    let hover = &infer_math.drag_pos;
    let chosen = &infer_math.chosen;
    let chosen_value = equation.get(chosen).unwrap();
    if hover[0] == chosen[0] {
        render_hover(ui, size, |ui| chosen_value.render(ui, size));
        return None;
    }
    render_hover(ui, size, |ui| (-chosen_value).render(ui, size));
    if hover.len() == 1 {
        if infer_math.released {
            let mut new_eq = Equation::new(Value::Num(0), Value::Num(0));
            let other_child = equation.child(hover[0]).unwrap().clone().into();
            let mut poly = Polynomial::new(vec![other_child]);
            let chosen_child = PolyChild::new(Sign::Neg, chosen_value.clone());
            poly.insert(infer_math.drag_sides[0] as usize, chosen_child);
            *new_eq.child_mut(hover[0]).unwrap() = Value::Poly(poly);
            Some(InferResult::NecAndSuf(PropContent::Eq(new_eq)))
        } else {
            infer_math.target_pos.push(hover[0]);
            infer_math.target_side = infer_math.drag_sides[0];
            None
        }
    } else {
        if let Value::Poly(polynomial) = equation.child(hover[0]).unwrap() {
            if infer_math.released {
                let mut new_eq = Equation::new(Value::Num(0), Value::Num(0));
                let mut new_poly = polynomial.clone();
                let chosen_child = PolyChild::new(Sign::Neg, chosen_value.clone());
                new_poly.insert(hover[1] + infer_math.drag_sides[1] as usize, chosen_child.clone());
                *new_eq.child_mut(hover[0]).unwrap() = Value::Poly(new_poly);
                Some(InferResult::NecAndSuf(PropContent::Eq(new_eq)))
            } else {
                infer_math.target_pos.extend_from_slice(&hover[..2]);
                infer_math.target_side = infer_math.drag_sides[1];
                None
            }
        } else {
            if infer_math.released {
                let mut new_eq = Equation::new(Value::Num(0), Value::Num(0));
                let other_child = equation.child(hover[0]).unwrap().clone().into();
                let mut poly = Polynomial::new(vec![other_child]);
                let chosen_child = PolyChild::new(Sign::Neg, chosen_value.clone());
                poly.insert(infer_math.drag_sides[0] as usize, chosen_child);
                *new_eq.child_mut(hover[0]).unwrap() = Value::Poly(poly);
                Some(InferResult::NecAndSuf(PropContent::Eq(new_eq)))
            } else {
                infer_math.target_pos.push(hover[0]);
                infer_math.target_side = infer_math.drag_sides[0];
                None
            }
        }
    }
}
fn render_hover(ui: &mut Ui, size: f32, add_contents: impl FnOnce(&mut Ui)) {
    let render_chosen = |ui: &mut Ui| {
        ui.horizontal(|ui| {
            set_math_font_size(ui, size);
            ui.style_mut().spacing.item_spacing.x = 0.0;
            add_contents(ui);
        });
    };
    egui::Area::new(Id::new("Moving"))
        .fixed_pos(ui.input(|i| {
            let mut pos = i.pointer.interact_pos().unwrap();
            pos.y -= size * 2.0;
            pos
        }))
        .show(ui.ctx(), |ui| {
            egui::Frame::popup(ui.style())
                .show(ui, render_chosen)
        });
}
fn update_inferring_value(ui: &mut Ui, value: &Value, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    let rect = if *pos == infer_math.chosen {
        let res = egui::Frame::none()
            .fill(ui.visuals().selection.bg_fill)
            .rounding(Rounding::same(2.0))
            .show(ui, |ui| {
                update_inferring_value_inner(ui, value, infer_math, size, pos);
            }).response.interact(Sense::drag());
        res.rect
    } else {
        child_ui(ui, |ui| {
            update_inferring_value_inner(ui, value, infer_math, size, pos);
        }).response.rect
    };
    render_drag_cursor(ui, rect, infer_math, size, pos);
    update_inferring_value_res(ui, value, rect, infer_math, pos);
}
fn render_drag_cursor(ui: &mut Ui, rect: Rect, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    if infer_math.target_pos == *pos {
        if infer_math.target_side == Side::Left {
            ui.painter().vline(rect.min.x, rect.min.y..=rect.min.y+size, Stroke::new(1.0, Color32::GRAY));
        } else {
            ui.painter().vline(rect.max.x, rect.min.y..=rect.min.y+size, Stroke::new(1.0, Color32::GRAY));
        }
        infer_math.target_pos.clear();
    }
}
fn update_inferring_value_res(ui: &mut Ui, value: &Value, rect: Rect, infer_math: &mut InferMath, pos: &mut Vec<usize>) {
    ui.input(|i| {
        let pointer = &i.pointer;
        if pointer.primary_clicked() && rect.contains(pointer.interact_pos().unwrap()) {
            if let Value::Num(_) | Value::Var(_) = value {
                infer_math.click_pos.extend_from_slice(pos);
            }
        } else if pointer.is_decidedly_dragging() {
            let cursor = pointer.interact_pos().unwrap();
            let middle = (rect.min.x + rect.max.x) * 0.5;
            if !rect.contains(cursor) {
                return;
            }
            if let Value::Num(_) | Value::Var(_) = value {
                infer_math.drag_pos.extend_from_slice(pos);
                infer_math.drag_sides = vec![Side::Left; pos.len()];
                if pointer.primary_released() {
                    infer_math.released = true
                } else {
                    infer_math.released = false
                }
            }
            if cursor.x < middle {
                infer_math.drag_sides[pos.len() - 1] = Side::Left;
            } else {
                infer_math.drag_sides[pos.len() - 1] = Side::Right;
            }
        }
    })
}
fn update_inferring_value_inner(ui: &mut Ui, value: &Value, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    match value {
        Value::Poly(polynomial) => update_inferring_poly(ui, polynomial, infer_math, size, pos),
        Value::Mono(monomial) => update_inferring_mono(ui, monomial, infer_math, size, pos),
        Value::Signed(signed) => update_inferring_signed(ui, signed, infer_math, size, pos),
        Value::Var(variable) => {
            no_select_label(ui, char_to_italic_str(variable.main));
        },
        Value::Num(number) => {
            no_select_label(ui, number.to_string());
        }
    };
}
fn update_bracket_inferring_value(ui: &mut Ui, value: &Value, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    let rect1 = no_select_label(ui, "(").rect;
    update_inferring_value(ui, value, infer_math, size, pos);
    let rect2 = no_select_label(ui, ")").rect;
    ui.input(|i| {
        let side = if let Some(pos) = i.pointer.interact_pos() {
            if rect1.contains(pos) {
                Side::Left
            } else if rect2.contains(pos) {
                Side::Right
            } else {
                return;
            }
        } else {
            return;
        };
        if i.pointer.primary_clicked() {
            infer_math.click_pos.extend_from_slice(pos)
        } else if i.pointer.is_decidedly_dragging() {
            infer_math.drag_pos.extend_from_slice(pos);
            infer_math.drag_sides = vec![side; pos.len()];
            if i.pointer.primary_released() {
                infer_math.released = true;
            } else {
                infer_math.released = false;
            }
        }
    })
    
}
fn update_sign_op(ui: &mut Ui, sign: Sign, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    let rect = child_ui(ui, |ui| {
        sign.render(ui, size);
    }).response.rect;
    ui.input(|i| {
        if i.pointer.is_decidedly_dragging() && rect.contains(i.pointer.interact_pos().unwrap()) {
            infer_math.drag_pos.extend_from_slice(pos);
            infer_math.drag_sides = vec![Side::Left; pos.len()];
            if i.pointer.primary_released() {
                infer_math.released = true;
            } else {
                infer_math.released = false;
            }
        } else if i.pointer.primary_clicked() && rect.contains(i.pointer.interact_pos().unwrap()) {
            infer_math.click_pos.extend_from_slice(pos)
        }
    });
}
fn update_poly_child_inner(ui: &mut Ui, child: &PolyChild, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    update_sign_op(ui, child.sign, infer_math, size, pos);
    update_inferring_value_inner(ui, &child.inner, infer_math, size, pos);
}
fn update_poly_child(ui: &mut Ui, child: &PolyChild, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    let rect = if *pos == infer_math.chosen {
        let res = egui::Frame::none()
            .fill(ui.visuals().selection.bg_fill)
            .rounding(Rounding::same(2.0))
            .show(ui, |ui| {
                update_poly_child_inner(ui, child, infer_math, size, pos);
            }).response.interact(Sense::drag());
        res.rect
    } else {
        child_ui(ui, |ui| {
            update_poly_child_inner(ui, child, infer_math, size, pos);
        }).response.rect
    };
    render_drag_cursor(ui, rect, infer_math, size, pos);
    update_inferring_value_res(ui, &child.inner, rect, infer_math, pos);
}
fn update_bracket_poly_child_inner(ui: &mut Ui, child: &PolyChild, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    update_sign_op(ui, child.sign, infer_math, size, pos);
    update_bracket_inferring_value(ui, &child.inner, infer_math, size, pos);
}
fn update_bracket_poly_child(ui: &mut Ui, child: &PolyChild, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    let rect = if *pos == infer_math.chosen {
        let res = egui::Frame::none()
            .fill(ui.visuals().selection.bg_fill)
            .rounding(Rounding::same(2.0))
            .show(ui, |ui| {
                update_bracket_poly_child_inner(ui, child, infer_math, size, pos);
            }).response.interact(Sense::drag());
        res.rect
    } else {
        child_ui(ui, |ui| {
            update_bracket_poly_child_inner(ui, child, infer_math, size, pos);
        }).response.rect
    };
    render_drag_cursor(ui, rect, infer_math, size, pos);
    update_inferring_value_res(ui, &child.inner, rect, infer_math, pos);
}
fn update_inferring_poly(ui: &mut Ui, poly: &Polynomial, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    let len = pos.len();
    pos.push(0);
    if let Sign::Neg = poly[0].sign {
        match poly[0].inner {
            Value::Signed(_) | Value::Poly(_) => update_bracket_poly_child(ui, &poly[0], infer_math, size, pos),
            _ => update_poly_child(ui, &poly[0], infer_math, size, pos)
        };
    } else {
        match poly[0].inner {
            Value::Poly(_) => update_bracket_inferring_value(ui, &poly[0].inner, infer_math, size, pos),
            _ => update_inferring_value(ui, &poly[0].inner, infer_math, size, pos)
        }
    }
    pos.truncate(len);
    for i in 1..poly.len() {
        pos.push(i);
        match poly[i].inner {
            Value::Signed(_) | Value::Poly(_) => update_bracket_poly_child(ui, &poly[i], infer_math, size, pos),
            _ => update_poly_child(ui, &poly[i], infer_math, size, pos)
        };
        pos.truncate(len);
    };
}
fn update_inferring_mono(ui: &mut Ui, mono: &Monomial, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    let len = pos.len();
    for i in 0..mono.len() {
        pos.push(i);
        match mono[i] {
            Value::Mono(_) | Value::Poly(_) | Value::Signed(_) => update_bracket_inferring_value(ui, &mono[i], infer_math, size, pos),
            _ => update_inferring_value(ui, &mono[i], infer_math, size, pos)
        };
        pos.truncate(len);
    }
}
fn update_inferring_signed(ui: &mut Ui, signed: &Signed, infer_math: &mut InferMath, size: f32, pos: &mut Vec<usize>) {
    pos.push(0);
    update_sign_op(ui, signed.sign, infer_math, size, pos);
    match &*signed.inner {
        Value::Poly(_) | Value::Signed(_) => update_bracket_inferring_value(ui, &signed.inner, infer_math, size, pos),
        _ => update_inferring_value(ui, &signed.inner, infer_math, size, pos)
    }
    pos.truncate(pos.len() - 1);
}